perm filename CLCOMP.MSG[COM,LSP]2 blob
sn#855381 filedate 1988-03-30 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00002 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002
C00003 ENDMK
C⊗;
∂29-Mar-88 2234 CL-Compiler-mailer Eval-When -- a radical view
Received: from labrea.Stanford.EDU by SAIL.Stanford.EDU with TCP; 29 Mar 88 22:34:24 PST
Received: by labrea.Stanford.EDU; Tue, 29 Mar 88 22:32:17 PST
Received: from bhopal.lucid.com by edsel id AA12080g; Tue, 29 Mar 88 22:24:31 PST
Received: by bhopal id AA01977g; Tue, 29 Mar 88 22:24:41 PST
Date: Tue, 29 Mar 88 22:24:41 PST
From: Jon L White <edsel!jonl@labrea.Stanford.EDU>
Message-Id: <8803300624.AA01977@bhopal.lucid.com>
To: Rob.MacLachlan@wb1.cs.cmu.edu
Cc: sandra@cs.utah.edu, cl-compiler@sail.stanford.edu
In-Reply-To: Rob.MacLachlan@WB1.CS.CMU.EDU's message of Sat, 26 Mar 88 12:38:29 EST <8803270744.AA29754@edsel.lucid.com>
Subject: Eval-When -- a radical view
You sure put "a mouthful" in your reply! I'm not sure that I'll be able now
to comment on all the things you've brought up, but here goes ...
re: A narrow complaint that I have is that it seems you haven't been as
consistent as you could be in extending the semantics described in CLTL.
In your version, compiling:
(eval-when (compile)
(eval-when (load)
(print 'foo)))
. . .
You're quite right; the code I suggested for EVAL-WHEN should have the line:
(:eval-before-compile T)
changed to be
(:eval-before-compile (or (memq 'eval situations)
(memq 'load situations)))
That should better reflect the semantics of what CLtL calls "compile-time-too".
re: It should also be clear that using a dynamic variable *EVAL-WHEN-STATE* is
an implementation detail, and not part of the inherent semantics. For one,
requiring EVAL to bind a special prevents it from being tail-recursive.
What you really want to do is lexically modify the evaluation rules. Using
a dynamic variable bound by EVAL and COMPILE is an approximation of this,
but things become more confusing when there are any other ways for the
lexical environment to become null.
Right again. Mostly my use of the dynamic variable *EVAL-WHEN-STATE* is
merely to make it easier to understand a rather simple defmacro definition
for EVAL-WHEN.
re: Even supposing we could clearly define EVAL-WHEN in a way that extended
cleanly across all implementations that we want to support, EVAL-WHEN
would still be bad because it is too powerful: it allows users to say
things that aren't meaningful across all implementations -- it encourages
writing of programs that don't work interpreted (or compiled).
This paragraph is representative of large section of your note, basically
saying that trying to "patch up" EVAL-WHEN is a doomed process. I disagree
mildly. In particular, the ability to "say things that aren't meaningful"
is not focused enough to warrant tossing out eval-when. I agree that the
willy-nilly generation of legal syntatic forms will come up with some
meaningless phrases; why, even my proposal presented an interpretation for
(defun foo (x)
(mumble (eval-when (load) (bletch x))))
even though that is clearly a meaningless thing to do. [my presentation was
to view the 'load' situation as meaning that this should be incorporated
into the compiled code and only into the compiled code; Sandra's presentation
-- at least verbally at the Friday morning meetings -- was that it could
mean something like #, and in a way I prefer hers now] Rather, I like the
simplicity of EVAL-WHEN for the combinations that do make good sense. As
you say,
I searched through our system sources looking for all uses of EVAL-WHEN.
Nearly all uses involved one of two situations lists:
(COMPILE LOAD EVAL)
(COMPILE EVAL)
. . .
There were also quite a few uses of the (COMPILE) situation list, but
nearly all of these were erroneous; the code wouldn't have worked
interpreted.
On the other hand, in our system, the relatively few instances of the (COMPILE)
situation are precisely for code that can't work interpreted. I myself have
even inserted a couple of lines like
(eval-when (eval)
(error "You Loser! this file can't be run interpretively"))
We have a few places in our system that are defined only by the code-generator
parts of the compiler; some of these functions have interpreter entries that
look like the classic:
(defun car (x)
(check-type x list)
(car x))
but most are merely internal compiler stuff that doesn't need such an entry.
Files that reference such functions simply can't be run except when compiled.
But the whole point is that whether the number of "meaningful" situations
is 3 or 4 or 5 out of a possible 8, that is no reason to give up just
because the other few are not particularly useful.
Now, Sandra brings up another good point (which you too, Rob, mention) --
The problem of having the same piece of code sometimes get evaluated in
the current lexical environment and sometimes not is going to be easy to
resolve. There does not seem to be much disagreement that the COMPILE
situation must do its evaluation in the null lexical environment. . . .
Maybe I'll exercise my perogative to bring in some "disagreement". Perhaps
feeding an &environment argument to eval-when isn't so bad after all. In
terms of my trial-baloon defmacro for eval-when, the only problematical point
is how to transmit an outter environment down through the code:
(mapc #'eval-internal code)
I'm sure that some suitable solution could be found. Maybe even binding
the *EVAL-WHEN-STATE* to it instead of :EVAL-BEFORE-COMPILE could work?
Also Sandra's mention of a possible definition of DEFMACRO in terms of
EVAL-WHEN and SETF(MACRO-FUNCTION ...) adds weight to the need for a solution.
At any rate, I think this is indeed an important enough problem to spend
some time thinking about [looking for a consistent solution that is, not
just looking for reasons to chuck out the whole kit-and-kaboodle].
If we were to adopt some notion that each "file" is a lexical entity --
equivalent for scoping as if there were a giant (locally ....) enclosing the
entire file -- then it would be even more important to pass in &environment
information to eval-when. [But of course you couldn't do this "enclosing"
literally since that would mean reading in all the forms of the file before
processing any of them]. My proposal for a lexical-file-proclaim needs
such a notion of lexical scoping, and I believe it accurately reflects
desiderata set out by Beckerele and others about the semantics of what
a "file" is such that you can apply COMPILE-FILE to it; but this is a
topic for yet another time.
Incidentally, the example that Sandra offers
(eval-when (eval compile load)
(let ((x (compute-some-value)))
(defmacro foo (y)
`(+ ,x ,y))))
Could just as well have been
(eval-when (eval compile)
(let ((x (compute-some-value)))
(defmacro foo (y)
`(+ ,x ,y))))
That is, the proponents of this style frequently need it only in the
compiler's environment. For an implementation that doesn't have an
interpreter, then the situation marker (eval compile) is still right,
since it means first compiling
(let ((x (compute-some-value)))
(defmacro foo (y)
`(+ ,x ,y)))
and then immediately afterwards calling that compiled "thunk" to be executed.
The macro is now "alive" for subsequent compilations of forms found later in
the file.
-- JonL --
∂29-Mar-88 2236 CL-Compiler-mailer Eval-When -- a radical view
Received: from labrea.Stanford.EDU by SAIL.Stanford.EDU with TCP; 29 Mar 88 22:36:03 PST
Received: by labrea.Stanford.EDU; Tue, 29 Mar 88 22:34:23 PST
Received: from bhopal.lucid.com by edsel id AA12136g; Tue, 29 Mar 88 22:31:34 PST
Received: by bhopal id AA01993g; Tue, 29 Mar 88 22:31:44 PST
Date: Tue, 29 Mar 88 22:31:44 PST
From: Jon L White <edsel!jonl@labrea.Stanford.EDU>
Message-Id: <8803300631.AA01993@bhopal.lucid.com>
To: jeff%aiva.edinburgh.ac.uk@nss.cs.ucl.ac.uk
Cc: cl-compiler@sail.stanford.edu, <@edsel,@labrea.stanford.edu:jonl>
In-Reply-To: Jeff Dalton's message of Mon, 28 Mar 88 17:00:29 bst <22121.8803281600@aiva.ed.ac.uk>
Subject: Eval-When -- a radical view
re: There is one subtlety that I think should be addressed, and that is:
what should implementations that always and only compile do? . . .
So maybe the top-level processor that is masquarading as "top-level EVAL"
should call a private entry into the compiler that doesn't rebind
*EVAL-WHEN-STATE*? I already had to presume such an entry to the
interpreter in the trial-balloon defmacro for EVAL-WHEN.
Even in the most minimal of implementations, I presume that LOAD differs
from COMPILE-FILE in that LOAD will successively "execute" each form
before even reading the next one. And COMPILE-FILE is called primarily
for the side-effect of creating a "binary" file. So it still makes sense
to me to have separate "situation" markers for :EVALUATING and :COMPILING,
even though serious portability questions arise about some combinations
of "situations".
-- JonL --
∂30-Mar-88 1055 CL-Compiler-mailer Eval-When -- a radical view
Received: from XX.LCS.MIT.EDU by SAIL.Stanford.EDU with TCP; 30 Mar 88 10:53:00 PST
Received: from LIVE-OAK.LCS.MIT.EDU by XX.LCS.MIT.EDU via Chaosnet; 30 Mar 88 11:00-EST
Received: from ACORN.Gold-Hill.DialNet.Symbolics.COM by MIT-LIVE-OAK.DialNet.Symbolics.COM via DIAL with SMTP id 85774; 30 Mar 88 10:11:55-EST
Received: from BOSTON.Gold-Hill.DialNet.Symbolics.COM by ACORN.Gold-Hill.DialNet.Symbolics.COM via CHAOS with CHAOS-MAIL id 97736; Wed 30-Mar-88 09:13:24-EST
Date: Wed, 30 Mar 88 09:15 est
From: mike%acorn@oak.lcs.mit.edu (mike@gold-hill.com after 1-April-88)
COMMENTS: NOTE %acorn@oak... CHANGES TO @GOLD-HILL.COM ON 1-April-88
To: edsel!jonl@labrea.Stanford.EDU
Subject: Eval-When -- a radical view
Cc: Rob.MacLachlan@wb1.cs.cmu.edu, sandra@cs.utah.edu,
cl-compiler@sail.stanford.edu
I searched through our system sources looking for all uses of
EVAL-WHEN.
Nearly all uses involved one of two situations lists:
(COMPILE LOAD EVAL)
(COMPILE EVAL)
In our implementation, the most common situation for eval-when is
(compile eval). This is used to exclude macros, constants, etc that
are compiled in to a delivered system. Another common one is
(load eval), which is used within expansions of macros to force loading
of runtime support: e.g.,
(defmacro mac (....)
`(progn
(eval-when (load eval) (require "runtime-support"))
...rest of expansion here....))
This is nice because in the file header you only have to require the
module that defines the macros, via:
(eval-when (compile eval) (require "the-macros")) You don't have to
know where the runtime support lives, or use autoloading or anything.
There are almost no uses of (compile eval load) anywhere.
I am of the opinion that we should define what EVAL-WHEN does, and
not chuck it out in favor of new constructs, like EVAL-EARLY, etc.
...mike beckerle